<template>
  <div id="gantt" ref="gantt" v-if="dataStatus === statusDict.OK">
    <div class="action_bar">
      <div class="action_left">
        <!-- 切换月份或者日期 -->
        <div class="action_button">
          <div :class="sizeDict.DAY === active ? 'active': ''" @click="active = sizeDict.DAY">日</div>
          <!-- <div :class="sizeDict.WEEK === active ? 'active': ''" @click="active = sizeDict.WEEK">周</div> -->
          <div :class="sizeDict.MONTH === active ? 'active': ''" @click="active = sizeDict.MONTH">月</div>
          <!-- <div :class="sizeDict.YEAR === active ? 'active': ''" @click="active = sizeDict.YEAR">年</div> -->
        </div>
        <div class="width_adjust">
          <span>宽度调节</span>
          <el-slider :min="0" :max="maxWidth" v-model="gantt_chart_width" />
        </div>
        <el-button size="mini" @click="isShowList = !isShowList" type="primary">{{isShowList ? '显示列表' : '隐藏列表'}}</el-button>
      </div>
      <div class="action_right">
        <!-- <el-button size="mini" type="success" @click="exportImage">导出为图片</el-button> -->
        <span class="full_screen_icon el-icon-full-screen" @click="fullScreen"></span>
      </div>
    </div>
    <div class="gantt_box" ref="gantt_box">
      <!-- 信息table -->
      <table class="gantt_container" cellspacing="0" v-if="!isShowList">
        <thead class="gantt_header">
          <tr>
            <th class="gantt_title">任务名称</th>
            <th class="gantt_title" style="width:85px;">开始</th>
            <th class="gantt_title" style="width:85px;">结束</th>
            <th class="gantt_title" style="width:60px;">持续/(天)</th>
            <th class="gantt_title">负责人</th>
            <!-- <th class="gantt_title">前置任务</th> -->
            <th class="gantt_title" style="width:60px;">完成进度</th>
            <th class="gantt_title" style="width:40px;"><span class="icon_add el-icon-plus"></span></th>
          </tr>
        </thead>
        <div class="split_line"></div>
        <tbody class="gantt_body gantt_child_td_padding">
          <!-- 渲染信息 -->
          <GanttRow :data="data" :listChange="listChange" :hideList="hideList" :editProcess="editProcess" :addItem="addItem" />
        </tbody>
      </table>
      <!-- 甘特图table -->
      <div class="gantt_content" :style="{width: gantt_chart_width +'px!important'}">
        <table class="gantt_container gantt_time">
          <!-- 选择月份 -->
          <thead ref="gantt_time" v-if="active === sizeDict.MONTH">
            <tr class="gantt_header">
              <!-- 渲染年份 -->
              <th v-for="item in dateList" :key="onlyKey('year' + item.value)" class="gantt_title" :colspan="item.children.length">{{item.value}}</th>
            </tr>
            <tr class="gantt_header">
              <!-- 渲染月份 -->
              <template v-for="item in dateList">
                <template v-for="item2 in item.children">
                  <td v-if="item2.value" :key="onlyKey('month' + item.value +'-' +item2.value)" ref="month_td" class="gantt_title" :style="{width: monthWidth + 'px'}">{{monthDict[item2.value]}}</td>
                </template>
              </template>
            </tr>
          </thead>
          <!-- 选择按日期 -->
          <thead ref="gantt_time" v-if="active === sizeDict.DAY">
            <tr class="gantt_header">
              <!-- 渲染月份 -->
              <template v-for="item in dateList">
                <template v-for="item2 in item.children">
                  <th :key="onlyKey('month'+ item.value +'-' +item2.value)" class="gantt_title" :colspan="item2.children.length">{{monthDict[item2.value]}}</th>
                </template>
              </template>
            </tr>
            <tr class="gantt_header">
              <!-- 渲染周几 -->
              <template v-for="item in dateList">
                <template v-for="item2 in item.children">
                  <template v-for="item3 in item2.children">
                    <td :key="onlyKey('week'+item.value +'-' + item2.value + '-' + item3)" class="gantt_title">{{weekDict[new Date(item.value +'-' + item2.value + '-' + item3).getDay()]}}</td>
                  </template>
                </template>
              </template>
            </tr>
            <tr class="gantt_header">
              <!-- 渲染日期 -->
              <template v-for="item in dateList">
                <template v-for="item2 in item.children">
                  <template v-for="item3 in item2.children">
                    <td :key="onlyKey('day-' + item.value +'-' + item2.value + '-' + item3)" ref="day_td" class="gantt_title">{{item3}}</td>
                  </template>
                </template>
              </template>
            </tr>
          </thead>
          <!-- 分割线 -->
          <div class="split_line"></div>
          <tbody class="gantt_body">
            <GanttProcess :data="data" :active="active" :startTagTime="startTagTime" :dateList="dateList" :dataList="{hideList}" />
            <!-- 今日线 -->
            <div class="today_line" v-if="active === sizeDict.DAY" :style="{left: (total_time(startTagTime, new Date()) - 1) * width + 6 + 'px'}"></div>
            <div class="today_line" v-else :style="{left: monthGrain(startTagTime, getFormatDate(new Date())) * monthWidth + 6 + 'px'}"></div>
          </tbody>
        </table>
      </div>
    </div>
  </div>
  <el-skeleton v-else-if="dataStatus === statusDict.LOADING" :rows="8" animated />
  <el-empty v-else>
    <el-button type="primary" @click="$router.go(-1)">返回</el-button>
  </el-empty>
</template>
<script>
import GanttRow from '@/components/GanttRow'
import GanttProcess from '@/components/GanttProcess'
import { width, weekDict, monthDict, sizeDict, onlyKey, monthWidth, statusDict } from '@/utils/GanttDicts'
import { currentProcess, total_time, monthGrain, getFormatDate } from '@/utils/GanttUtil'
import html2canvas from 'html2canvas'

export default {
  data() {
    return {
      width, weekDict, monthDict, sizeDict, onlyKey, monthWidth, currentProcess, total_time, monthGrain, getFormatDate,
      active: 'day',
      statusDict,
      /**
       *  dateList: {
       *    value: 'year',
       *    children: [ 
       *      value:'month'
       *      children: []  
       *    ]
       *  }
       */
      dateList: {},
      gantt_chart_width: 1300,
      maxWidth: 2000,
      hideList: {},
      startTagTime: '1970-09-01',
      parentTime: {
        startTime: '',
        endTime: ''
      },
      headerLength: 0,
      isShowList: false,
      dataStatus: this.status
    }
  },
  props: {
    data: {
      type: Array,
      default: () => []
    },
    addItem: {
      type: Function,
      default: function (item) {
        this.$message({ message: '保存成功，请查看控制台，自定义请添加addItem函数', type: 'success' });
        console.log(item);
      }
    },
    editProcess: {
      type: Function,
      default: function (item, msg) {
        this.$message({ message: '修改成功，请查看控制台，自定义请添加editProcess函数', type: 'success' });
        console.log(item, msg);
      }
    },
    status: {
      type: String,
      default: statusDict.LOADING,
    }
  },
  components: { GanttRow, GanttProcess },
  created() {
    if (this.data.length) {
      this.getDateList();
      this.startTagTime = this.data[0].startTime;
    }
  },
  watch: {
    data() {
      this.dataStatus = this.data.length ? this.statusDict.OK : this.statusDict.NO;
      if (!this.data.length) return
      this.getDateList();
      this.startTagTime = this.data[0].startTime;
      this.$nextTick(() => {
        this.maxWidth = this.maxWidthValue();
        this.$refs.gantt.addEventListener("fullscreenchange", () => this.maxWidth = this.maxWidthValue());
      });
    },
    active() {
      this.$nextTick(() => {
        this.headerLength = this.active === this.sizeDict.MONTH ? this.$refs.month_td.length : this.$refs.day_td.length
        this.maxWidth = this.maxWidthValue();
        this.gantt_chart_width = this.maxWidth
      })
    },
    status() {
      this.dataStatus = this.status
    }
  },
  methods: {
    // 导出为图片
    // exportImage() {
      // html2canvas(document.querySelector(".gantt_box")).then(canvas => {
      //   const a = document.createElement('a');
      //   a.href = canvas.toDataURL("image/png");
      //   a.download = this.data[0].taskName + '.png';
      //   a.click();
      // });
    // },
    // 最大宽度值
    maxWidthValue() {
      let maxWidthObj = {
        [this.sizeDict.MONTH]: this.headerLength * this.monthWidth + 2,
        [this.sizeDict.DAY]: this.$refs.gantt_box.clientWidth
      }
      return maxWidthObj[this.active] || this.$refs.gantt_box.clientWidth || 2000;
    },
    // 切出年份数组
    getDateList() {
      const startTime = new Date(this.data[0].startTime).getTime();
      const endTime = new Date(this.data[0].endTime).getTime();
      const oneDay = 1000 * 60 * 60 * 24;
      for (let nextTime = startTime; nextTime <= endTime; nextTime += oneDay) {
        let year = this.formatDate(nextTime);
        // 如果不存在该年
        if (!this.dateList[year]) this.dateList[year] = { value: year, children: [] }
        let month = this.formatDate(nextTime, 'MM');
        // 查询该月份是否存在
        let monthIndex = this.dateList[year].children.findIndex(item => item.value === month);
        // 不存在添加该月
        if (monthIndex === -1) {
          this.dateList[year].children.push({ value: this.formatDate(nextTime, 'MM'), children: [] });
          // 重新查找
          monthIndex = this.dateList[year].children.findIndex(item => item.value === month);
        }
        let date = this.formatDate(nextTime, 'dd');
        this.dateList[year].children[monthIndex].children.push(date);
      }
      this.$forceUpdate();
      // console.log(this.dateList);
    },
    // 时间格式化
    formatDate(time, type = 'yy') {
      const date = new Date(time);
      const typeObj = {
        'yy': `${date.getFullYear()}`,
        'MM': `${date.getMonth() + 1}`.padStart(2, '0'),
        'dd': `${date.getDate()}`.padStart(2, '0'),
      }
      return typeObj[type];
    },
    // 展开 / 关闭
    listChange(id) {
      this.hideList[id] = !this.hideList[id];
      // console.log(this.hideList);
      this.$forceUpdate();
    },
    // 全屏
    fullScreen() {
      this.$refs.gantt.requestFullscreen().then();
    }
  },
}
</script>

<style lang="scss" >
$border-color: #eeeeee;
$font-color: #666;
$title-border-color: #dbdbdb;
$bg-color: #409eff;
$icon-color: #909399;

table,
thead,
tbody,
tr,
th,
td {
  margin: 0;
  padding: 0;
}
td {
  empty-cells: show;
  // padding: 0px 5px;
}
tbody td {
  max-height: 30px;
  height: 40px;
  max-width: 100px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
table {
  border-collapse: collapse;
  width: 100%;
  height: 100%;
}
thead {
  height: 60px;
}
#gantt {
  user-select: none;
  background-color: #fff;
  padding: 10px;
  min-height: 350px;
  // 分割线
  .split_line {
    height: 8px;
  }
  // 操作栏
  .action_bar {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
    font-size: 14px;
    // 左侧
    .action_left {
      display: flex;
      .action_button {
        display: flex;
        border: 1px solid $bg-color;
        border-radius: 5px;
        color: $font-color;
        cursor: pointer;
        overflow: hidden;
        .active {
          background-color: $bg-color;
          color: #fff;
        }
        div {
          padding: 5px 10px;
          &:nth-of-type(n + 2) {
            border-left: 1px solid $bg-color;
          }
        }
      }
      // 进度条
      .width_adjust {
        font-size: 13px;
        display: flex;
        width: 250px;
        align-items: center;
        span {
          display: inline-block;
          margin-left: 15px;
          margin-right: 5px;
        }
        .el-slider {
          width: 150px;
          height: 20px;
          .el-slider__runway {
            margin: 8px 0;
          }
          .el-slider__button {
            width: 10px;
            height: 10px;
          }
        }
      }
    }
    // 右侧
    .action_right {
      display: flex;
      align-items: center;
      .full_screen_icon {
        display: inline-block;
        font-size: 24px;
        font-weight: 800;
        color: $icon-color;
        cursor: pointer;
        margin-left: 20px;
      }
    }
  }
  // 栏目
  .gantt_box {
    display: flex;
    font-size: 12px;
    .gantt_container {
      flex: 1;
      border-collapse: collapse;
      border-left: 1px solid $border-color;
      th {
        font-weight: normal;
      }
      .gantt_header {
        // border: 1px solid $border-color;
        background-color: #f3f5f7;
        .gantt_title {
          min-width: 40px;
          // 第二个标题开始设置左边线条
          &:nth-of-type(n + 2) {
            border-left: 1px solid $title-border-color;
          }
        }
      }
      .gantt_body {
        color: $font-color;
        border-top: 1px solid $border-color;
        border-bottom: 1px solid $border-color;
        position: relative;
        // 第二行开始加顶部线条
        tr:nth-of-type(n + 2) {
          border-top: 1px solid $border-color;
        }
        // 第二列开始设置 左边线条
        td:nth-of-type(n + 2) {
          border-left: 1px solid $border-color;
        }
      }
      .gantt_child_td_padding {
        td {
          padding: 0 5px;
        }
      }
    }
    // 右侧内容滚动
    .gantt_content {
      overflow-x: scroll;
      border-left: 1px solid $border-color;
      border-right: 1px solid $border-color;
      &::-webkit-scrollbar {
        /*滚动条整体样式*/
        width: 10px; /*高宽分别对应横竖滚动条的尺寸*/
        height: 10px;
        scrollbar-arrow-color: $border-color;
      }
      &::-webkit-scrollbar-thumb {
        /*滚动条里面小方块*/
        border-radius: 999px;
        background: #999;
        scrollbar-arrow-color: $border-color;
      }
      &::-webkit-scrollbar-track {
        /*滚动条里面轨道*/
        border-radius: 0;
        // background: rgba(0,0,0,0.1);
        background: $border-color;
        border-radius: 999px;
      }
    }
    .gantt_time {
      color: $font-color;
      th {
        padding: 5px;
      }
    }
  }
  // 进度条定位
  .progress_position {
    position: relative;
    overflow: hidden;
  }
  .progress_total {
    position: absolute;
    top: 3px;
  }
  .progress_ing {
    position: absolute;
    top: 20px;
  }
  // 按钮
  .icon_type {
    cursor: pointer;
    color: $bg-color;
    display: inline-block;
    font-size: 13px;
    margin-left: 5px;
  }
  .icon_add {
    display: block;
    width: 100%;
    font-size: 16px;
    font-weight: 800;
    text-align: center;
    color: $bg-color;
    cursor: pointer;
  }
}
.mouse_hover:hover {
  background-color: #f5f7fa;
}
.today_line {
  position: absolute;
  z-index: 2;
  top: 3px;
  bottom: 0;
  width: 3px;
  height: calc(100% - 3px);
  background-color: rgba(103, 194, 58, 0.6);
  &::before {
    content: "today";
    background-color: rgba(103, 194, 58, 0.6);
    padding: 2px 5px;
    color: rgba($color: #fff, $alpha: 0.8);
  }
}
</style>